//
// Created by alexa on 5/13/2024.
//

#include "MissileRepository.h"

#include <fstream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

Missile *MissileRepository::findById(string id) {
    return source.getById(id);
}

void MissileRepository::save(Missile *missile) {
    if (!source.getById(missile->getId())) {
        source.add(missile);
    }
    if (!fileSourcePath.empty()) {
        saveDataToFile();
    }
}

void MissileRepository::deleteOne(Missile *missile) {
    if (source.getById(missile->getId())) {
        source.removeById(missile->getId());
    }
    if (!fileSourcePath.empty()) {
        saveDataToFile();
    }
}

vector<Missile *> MissileRepository::findAll() {
    return source.getAll();
}

void MissileRepository::saveDataToFile() {
    ofstream file(fileSourcePath);

    json jarr = json::array();

    vector<Missile *> list = findAll();

    for (const auto &el: list) {
        json jobj = json::object();
        jobj["id"] = el->getId();
        jobj["name"] = el->getName();
        jobj["calibre"] = el->getCalibre();
        jobj["length"] = el->getLength();
        jobj["weight"] = el->getWeight();
        jobj["flightRange"] = el->getFlightRange();
        jobj["impactArea"] = el->getImpactArea();
        jobj["speed"] = el->getSpeed();
        jarr.push_back(jobj);
    }
    file << jarr.dump(4) << endl;
    file.close();
}

void MissileRepository::loadDataFromFile() {
    if (fileSourcePath.empty()) return;
    ifstream file(fileSourcePath);
    if (!file.good()) {
        file.close();
        return;
    }
    json data;
    try {
        data = json::parse(file);
    } catch (json::exception &pass) {
        file.close();
        return;
    }
    if (!data.is_array()) return;
    for (const auto &el: data) {
        try {
            string id = el.at("id");
            string name = el.at("name");
            int calibre = el.at("calibre");
            float flightRange = el.at("flightRange");
            float impactArea = el.at("impactArea");
            float length = el.at("length");
            float weight = el.at("weight");
            float speed = el.at("speed");
            Missile *missile = new Missile(name, calibre, length, weight, flightRange, impactArea, speed);
            missile->setId(id);
            this->source.add(missile);
        } catch (json::exception &e) {
            continue;
        }
    }
}

const string &MissileRepository::getFileSourcePath() const {
    return fileSourcePath;
}

void MissileRepository::setFileSourcePath(const string &fileSourcePath) {
    this->fileSourcePath = fileSourcePath;
    if (!fileSourcePath.empty()) {
        loadDataFromFile();
    }
}

MissileRepository::MissileRepository(const string &fileSourcePath) : fileSourcePath(fileSourcePath) {
    if (!fileSourcePath.empty()) {
        loadDataFromFile();
    }
}

MissileRepository::~MissileRepository() {
    vector<Missile *> list = findAll();
    for (auto &el: list) {
        delete el;
    }
}
